package main

import (
	"context"
	"encoding/base64"
	"encoding/json"
	"fmt"
	"os"
	"os/exec"
	"path/filepath"
	"regexp"
	"runtime"
	"strings"
	"time"

	"batch-document-generator/internal/services"
	"github.com/google/uuid"
	wailsRuntime "github.com/wailsapp/wails/v2/pkg/runtime"
)

// App struct
type App struct {
	ctx                context.Context
	templateService    *services.TemplateService
	ocrService         *services.OCRService
	siliconFlowService *services.SiliconFlowService
	fieldMappingService *services.FieldMappingService
	configService      *services.ConfigService
	fileService        *services.FileService
	batchOCRService    *services.BatchOCRService
	smartExtractService *services.SmartExtractService
}

// NewApp creates a new App application struct
func NewApp() *App {
	configService := services.NewConfigService()
	
	// 加载配置并初始化服务
	config, _ := configService.LoadConfig()
	siliconFlowService := services.NewSiliconFlowService()
	if config.SiliconFlowAPIKey != "" {
		siliconFlowService.SetAPIKey(config.SiliconFlowAPIKey)
	}
	
	fieldMappingService := services.NewFieldMappingService()
	
	return &App{
		templateService:     services.NewTemplateService(),
		ocrService:           services.NewOCRService(),
		siliconFlowService:   siliconFlowService,
		fieldMappingService: fieldMappingService,
		configService:        configService,
		fileService:          services.NewFileService(),
		batchOCRService:      services.NewBatchOCRService(siliconFlowService),
		smartExtractService:  services.NewSmartExtractService(fieldMappingService),
	}
}

// startup is called when the app starts. The context is saved
// so we can call the runtime methods
func (a *App) startup(ctx context.Context) {
	a.ctx = ctx
}

func (a *App) domReady(ctx context.Context) {
	// DOM ready
}

func (a *App) shutdown(ctx context.Context) {
	// Cleanup
}

// ========== 模板相关方法 ==========

// CreateTemplate 创建文本模板
func (a *App) CreateTemplate(name, content string) (string, error) {
	template := services.Template{
		ID:        uuid.New().String(),
		Name:      name,
		Type:      "text",
		Content:   content,
		Variables: extractVariables(content),
		CreatedAt: time.Now().Format("2006-01-02 15:04:05"),
		UpdatedAt: time.Now().Format("2006-01-02 15:04:05"),
	}
	
	err := a.templateService.SaveTemplate(template)
	if err != nil {
		return "", err
	}
	
	data, _ := json.Marshal(template)
	return string(data), nil
}

// CreateDocxTemplate 创建 DOCX 模板
func (a *App) CreateDocxTemplate(name string, base64Data string) (string, error) {
	// 解码 base64
	base64Str := base64Data
	if idx := strings.Index(base64Str, ","); idx != -1 {
		base64Str = base64Str[idx+1:]
	}
	
	docxData, err := base64.StdEncoding.DecodeString(base64Str)
	if err != nil {
		return "", err
	}
	
	templateID := uuid.New().String()
	
	// 保存 DOCX 文件
	filePath, err := a.templateService.SaveDocxTemplate(templateID, docxData)
	if err != nil {
		return "", err
	}
	
	// 提取变量
	docxService := services.NewDocxService()
	variables, err := docxService.ExtractVariablesFromDocx(filePath)
	if err != nil {
		// 如果提取失败，使用空数组
		variables = []string{}
	}
	
	// 确保 variables 不是 nil
	if variables == nil {
		variables = []string{}
	}
	
	template := services.Template{
		ID:        templateID,
		Name:      name,
		Type:      "docx",
		FilePath:   filePath,
		Variables: variables,
		CreatedAt: time.Now().Format("2006-01-02 15:04:05"),
		UpdatedAt: time.Now().Format("2006-01-02 15:04:05"),
	}
	
	err = a.templateService.SaveTemplate(template)
	if err != nil {
		return "", err
	}
	
	data, _ := json.Marshal(template)
	return string(data), nil
}

// GetTemplate 获取模板
func (a *App) GetTemplate(id string) (string, error) {
	template, err := a.templateService.LoadTemplate(id)
	if err != nil {
		return "", err
	}
	
	data, err := json.Marshal(template)
	if err != nil {
		return "", err
	}
	
	return string(data), nil
}

// ListTemplates 列出所有模板（使用缓存）
func (a *App) ListTemplates() (string, error) {
	templates, err := a.templateService.ListTemplates()
	if err != nil {
		return "[]", err
	}
	
	data, err := json.Marshal(templates)
	if err != nil {
		return "[]", err
	}
	
	return string(data), nil
}

// RefreshTemplatesCache 刷新模板缓存
func (a *App) RefreshTemplatesCache() {
	a.templateService.RefreshCache()
}

// UpdateTemplate 更新模板
func (a *App) UpdateTemplate(id, name, content string) (string, error) {
	template, err := a.templateService.LoadTemplate(id)
	if err != nil {
		return "", err
	}
	
	template.Name = name
	template.Content = content
	template.Variables = extractVariables(content)
	template.UpdatedAt = time.Now().Format("2006-01-02 15:04:05")
	
	err = a.templateService.SaveTemplate(*template)
	if err != nil {
		return "", err
	}
	
	data, _ := json.Marshal(template)
	return string(data), nil
}

// DeleteTemplate 删除模板
func (a *App) DeleteTemplate(id string) error {
	return a.templateService.DeleteTemplate(id)
}

// SelectTemplatesFolder 选择模板文件夹（使用系统对话框）
func (a *App) SelectTemplatesFolder() (string, error) {
	folderPath, err := wailsRuntime.OpenDirectoryDialog(a.ctx, wailsRuntime.OpenDialogOptions{
		Title: "选择模板文件夹",
	})
	if err != nil {
		return "", err
	}
	return folderPath, nil
}

// ImportTemplatesFromFolder 从文件夹导入模板
func (a *App) ImportTemplatesFromFolder(folderPath string) (string, error) {
	templates, err := a.templateService.ImportTemplatesFromFolder(folderPath)
	if err != nil {
		return "", err
	}
	
	// 保存模板文件夹路径到配置
	config, _ := a.configService.LoadConfig()
	if config != nil {
		config.TemplatesFolder = folderPath
		a.configService.SaveConfig(config)
	}
	
	data, err := json.Marshal(templates)
	if err != nil {
		return "", err
	}
	
	return string(data), nil
}

// GetDefaultTemplatesFolder 获取默认模板文件夹
func (a *App) GetDefaultTemplatesFolder() string {
	return a.templateService.GetDefaultTemplatesFolder()
}

// ========== OCR 相关方法 ==========

// RecognizeImage OCR 识别图片
func (a *App) RecognizeImage(imagePath string) (string, error) {
	result, err := a.ocrService.RecognizeImage(imagePath)
	if err != nil {
		return "", err
	}
	
	data, err := json.Marshal(result)
	if err != nil {
		return "", err
	}
	
	return string(data), nil
}

// SetOCRConfig 设置 OCR API 配置
func (a *App) SetOCRConfig(url, key, secret string) {
	a.ocrService.SetAPIConfig(url, key, secret)
}

// ========== 配置相关方法 ==========

// GetAppConfig 获取应用配置
func (a *App) GetAppConfig() (string, error) {
	config, err := a.configService.GetConfig()
	if err != nil {
		return "", err
	}
	
	data, err := json.Marshal(config)
	if err != nil {
		return "", err
	}
	
	return string(data), nil
}

// SaveAppConfig 保存应用配置
func (a *App) SaveAppConfig(configJSON string) error {
	var config services.AppConfig
	err := json.Unmarshal([]byte(configJSON), &config)
	if err != nil {
		return err
	}
	
	// 如果更新了 API Key，同步更新服务
	if config.SiliconFlowAPIKey != "" {
		a.siliconFlowService.SetAPIKey(config.SiliconFlowAPIKey)
	}
	
	return a.configService.SaveConfig(&config)
}

// ========== SiliconFlow 相关方法 ==========

// SetSiliconFlowAPIKey 设置 SiliconFlow API Key
func (a *App) SetSiliconFlowAPIKey(apiKey string) {
	a.siliconFlowService.SetAPIKey(apiKey)
	config, _ := a.configService.LoadConfig()
	if config != nil {
		config.SiliconFlowAPIKey = apiKey
		a.configService.SaveConfig(config)
	}
}

// GetSiliconFlowModels 获取 SiliconFlow 模型列表
func (a *App) GetSiliconFlowModels() (string, error) {
	models, err := a.siliconFlowService.GetModels()
	if err != nil {
		return "[]", err
	}
	
	data, err := json.Marshal(models)
	if err != nil {
		return "[]", err
	}
	
	return string(data), nil
}

// RecognizeImageWithSiliconFlowStream 使用 SiliconFlow 流式识别图片
func (a *App) RecognizeImageWithSiliconFlowStream(modelID string, imageBase64 string) error {
	go func() {
		err := a.siliconFlowService.RecognizeImageStream(modelID, imageBase64, func(chunk string) {
			wailsRuntime.EventsEmit(a.ctx, "ocr-stream-chunk", chunk)
		})
		if err != nil {
			wailsRuntime.EventsEmit(a.ctx, "ocr-stream-error", err.Error())
		} else {
			wailsRuntime.EventsEmit(a.ctx, "ocr-stream-done", "")
		}
	}()
	return nil
}

// ========== 字段映射相关方法 ==========

// GetFieldMapping 获取模板的字段映射规则
func (a *App) GetFieldMapping(templateID string) (string, error) {
	mapping, err := a.fieldMappingService.GetMapping(templateID)
	if err != nil {
		return "", err
	}
	
	data, err := json.Marshal(mapping)
	if err != nil {
		return "", err
	}
	
	return string(data), nil
}

// SaveFieldMapping 保存模板的字段映射规则
func (a *App) SaveFieldMapping(mappingJSON string) error {
	var mapping services.FieldMapping
	err := json.Unmarshal([]byte(mappingJSON), &mapping)
	if err != nil {
		return err
	}
	
	return a.fieldMappingService.SaveMapping(mapping)
}

// ApplyFieldMapping 应用字段映射，将 OCR 结果转换为模板变量
func (a *App) ApplyFieldMapping(templateID string, ocrDataJSON string) (string, error) {
	var ocrData map[string]interface{}
	err := json.Unmarshal([]byte(ocrDataJSON), &ocrData)
	if err != nil {
		return "", err
	}
	
	result, err := a.fieldMappingService.ApplyMapping(templateID, ocrData)
	if err != nil {
		return "", err
	}
	
	data, err := json.Marshal(result)
	if err != nil {
		return "", err
	}
	
	return string(data), nil
}

// SaveImageFile 保存图片文件到临时目录（接收 base64 编码的数据）
func (a *App) SaveImageFile(filename string, base64Data string) (string, error) {
	// 解码 base64（去掉 data:image/xxx;base64, 前缀）
	base64Str := base64Data
	if idx := strings.Index(base64Str, ","); idx != -1 {
		base64Str = base64Str[idx+1:]
	}
	
	data, err := base64.StdEncoding.DecodeString(base64Str)
	if err != nil {
		return "", err
	}
	
	homeDir, _ := os.UserHomeDir()
	tempDir := filepath.Join(homeDir, ".batch-doc-generator", "temp")
	os.MkdirAll(tempDir, 0755)
	
	filePath := filepath.Join(tempDir, filename)
	err = os.WriteFile(filePath, data, 0644)
	if err != nil {
		return "", err
	}
	
	return filePath, nil
}

// ========== 文件相关方法 ==========

// FillAndSaveTemplate 填充模板并保存
func (a *App) FillAndSaveTemplate(templateID, dataJSON, filename string) (string, error) {
	var data map[string]string
	err := json.Unmarshal([]byte(dataJSON), &data)
	if err != nil {
		return "", err
	}
	
	// 获取输出目录
	outputDir := a.fileService.GetOutputDir()
	outputPath := filepath.Join(outputDir, filename)
	
	// 填充模板
	filePath, err := a.templateService.FillTemplate(templateID, data, outputPath)
	if err != nil {
		return "", err
	}
	
	return filePath, nil
}

// GetOutputDir 获取输出目录
func (a *App) GetOutputDir() string {
	return a.fileService.GetOutputDir()
}

// OpenFile 使用系统默认程序打开文件
func (a *App) OpenFile(filePath string) error {
	var cmd *exec.Cmd
	
	switch runtime.GOOS {
	case "windows":
		// 使用 start 命令打开文件，第一个空字符串是窗口标题
		cmd = exec.Command("cmd", "/c", "start", "", filePath)
	case "darwin":
		cmd = exec.Command("open", filePath)
	case "linux":
		cmd = exec.Command("xdg-open", filePath)
	default:
		return fmt.Errorf("不支持的操作系统: %s", runtime.GOOS)
	}
	
	return cmd.Run()
}

// ========== 批量OCR相关方法 ==========

// SelectMaterialsFolder 选择材料文件夹
func (a *App) SelectMaterialsFolder() (string, error) {
	folderPath, err := wailsRuntime.OpenDirectoryDialog(a.ctx, wailsRuntime.OpenDialogOptions{
		Title: "选择材料文件夹",
	})
	if err != nil {
		return "", err
	}
	return folderPath, nil
}

// RecognizeFolder 批量识别文件夹中的图片
func (a *App) RecognizeFolder(folderPath string, modelID string) (string, error) {
	// 使用事件发送进度
	result, err := a.batchOCRService.RecognizeFolder(folderPath, modelID, func(current, total int, fileName string) {
		progress := map[string]interface{}{
			"current":  current,
			"total":    total,
			"fileName": fileName,
		}
		progressJSON, _ := json.Marshal(progress)
		wailsRuntime.EventsEmit(a.ctx, "batch-ocr-progress", string(progressJSON))
	})
	
	if err != nil {
		return "", err
	}
	
	data, err := json.Marshal(result)
	if err != nil {
		return "", err
	}
	
	return string(data), nil
}

// ExtractFieldsFromOCR 从OCR结果中智能提取匹配模板字段的内容
func (a *App) ExtractFieldsFromOCR(templateID string, ocrDataJSON string, ocrText string) (string, error) {
	var ocrData map[string]interface{}
	err := json.Unmarshal([]byte(ocrDataJSON), &ocrData)
	if err != nil {
		return "", err
	}
	
	// 获取模板变量列表
	template, err := a.templateService.LoadTemplate(templateID)
	if err != nil {
		return "", err
	}
	
	variables := template.Variables
	if variables == nil {
		variables = []string{}
	}
	
	// 提取字段
	result, err := a.smartExtractService.ExtractFieldsWithVariables(templateID, variables, ocrData, ocrText)
	if err != nil {
		return "", err
	}
	
	data, err := json.Marshal(result)
	if err != nil {
		return "", err
	}
	
	return string(data), nil
}

// ========== 工具方法 ==========

// extractVariables 从模板内容中提取变量（支持中文）
func extractVariables(content string) []string {
	var variables []string
	seen := make(map[string]bool)
	
	// 使用正则表达式匹配 {{变量名}}，支持中文
	re := regexp.MustCompile(`\{\{([^}]+)\}\}`)
	matches := re.FindAllStringSubmatch(content, -1)
	
	for _, match := range matches {
		if len(match) > 1 {
			varName := strings.TrimSpace(match[1])
			if varName != "" && !seen[varName] {
				variables = append(variables, varName)
				seen[varName] = true
			}
		}
	}
	
	return variables
}

